#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "hardware/timer.h"
#include "log.h"
#include "httpd_fs.h"
#include "hardware/claim.h"

#define LOG_BUFFER_SIZE (1024 * 4)

static char g_log_buffer[LOG_BUFFER_SIZE];
static uint32_t g_log_write_cnt;
static uint32_t g_log_read_cnt;
void log_init(void)
{
    g_log_write_cnt = 0;
    g_log_read_cnt = 0;
}

void log_printf(const char *format, ...)
{
    char buffer[256];
    static uint32_t index = 0;
    va_list args;
    int len;
    uint32_t time = time_us_32();
    uint32_t save;
    
    save = hw_claim_lock();
    len = snprintf(buffer, sizeof(buffer), "%d.[%d.%03d] ", (int)index++ , (int)time / 1000000, (int)(time / 1000) % 1000);
    va_start(args, format);
    len += vsnprintf(&buffer[len], sizeof(buffer) - len, format, args);
    for (int i = 0; i < len; i++) {
        g_log_buffer[g_log_write_cnt % LOG_BUFFER_SIZE] = buffer[i];
        g_log_write_cnt++;
    }
    hw_claim_unlock(save);
}

void log_printf_raw(const char *format, ...)
{
    char buffer[256];
    va_list args;
    int len;

    va_start(args, format);
    len = vsnprintf(&buffer[len], sizeof(buffer) - len, format, args);
    for (int i = 0; i < len; i++) {
        g_log_buffer[g_log_write_cnt % LOG_BUFFER_SIZE] = buffer[i];
        g_log_write_cnt++;
    }
}

static int log_read(char *buf, int len)
{
    if ((g_log_write_cnt - g_log_read_cnt) > LOG_BUFFER_SIZE) {
        g_log_read_cnt = g_log_write_cnt -  LOG_BUFFER_SIZE;
    }
    for (int i = 0; i < len; i++) {
        if (g_log_read_cnt == g_log_write_cnt) {
            return i;
        }
        buf[i] = g_log_buffer[g_log_read_cnt % LOG_BUFFER_SIZE];
        g_log_read_cnt++;
    }
    return len;
}

static int fs_open_log_txt(struct fs_file *file, const char *name, void **priv)
{
  char buffer[512] = {0};
  int len = 0;

  len = log_read(buffer, sizeof(buffer) - 1);

  file->len = len;
  file->index = file->len;
  file->data = malloc(file->len+ 1);
  file->flags = 0;
  strcpy((char *)file->data, buffer);
  return 1;
}

HTTPD_FILE_DEFINE("/log.txt", fs_open_log_txt, NULL, NULL, NULL);
